package com.zc.timedown.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.List;

import com.zc.common.utils.DateUtils;
import com.zc.timedown.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zc.timedown.mapper.TimeRecordMapper;
import com.zc.timedown.domain.TimeRecord;
import com.zc.timedown.service.ApiTimeRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 时间账本Service业务层处理
 *
 * @author zc
 * @date 2025-10-21
 */
@Service
public class ApiTimeRecordServiceImpl extends ServiceImpl<TimeRecordMapper, TimeRecord> implements ApiTimeRecordService
{
    @Autowired
    private TimeRecordMapper timeRecordMapper;

    /**
     * 查询时间账本
     *
     * @param id 时间账本主键
     * @return 时间账本
     */
    @Override
    public TimeRecord selectTimeRecordById(Long id)
    {
                return getById(id);
    }

    /**
     * 查询时间账本列表
     *
     * @param timeRecord 时间账本
     * @return 时间账本
     */
    @Override
    public List<TimeRecord> selectTimeRecordList(TimeRecord timeRecord)
    {
        return timeRecordMapper.selectTimeRecordList(timeRecord);
    }

    /**
     * 新增时间账本
     *
     * @param timeRecord 时间账本
     * @return 结果
     */
    @Override
    public int insertTimeRecord(TimeRecord timeRecord)
    {
        if (!isBetweenZeroAndTwentyFour(timeRecord.getDurationHours())){
            throw new RuntimeException("单次记录时间不能超过24小时或小于等于0小时");
        }
        // 计算当天已记录的总时间
        BigDecimal totalHoursToday = timeRecordMapper.getTotalHoursByUserIdAndDate(
                timeRecord.getUserId(),
                timeRecord.getRecordDate()
        );

        // 如果当天已有记录，检查加上新记录是否会超过24小时
        if (totalHoursToday != null) {
            BigDecimal newTotal = totalHoursToday.add(timeRecord.getDurationHours());
            if (newTotal.compareTo(new BigDecimal("24")) > 0) {
                throw new RuntimeException("当天累计时间不能超过24小时");
            }
        }

                timeRecord.setCreateTime(DateUtils.getNowDate());
                return save(timeRecord) == true? 1 : 0;
    }


        private boolean isBetweenZeroAndTwentyFour(BigDecimal value) {
            // 确保value不为null
            if (value == null) {
                return false;
            }

            // 判断value > 0 且 value < 24
            return value.compareTo(BigDecimal.ZERO) > 0 &&
                    value.compareTo(new BigDecimal("24")) <= 0;
        }


    /**
     * 修改时间账本
     *
     * @param timeRecord 时间账本
     * @return 结果
     */
    @Override
    public int updateTimeRecord(TimeRecord timeRecord)
    {
                timeRecord.setUpdateTime(DateUtils.getNowDate());
                return updateById(timeRecord) == true ? 1 : 0;
    }

    /**
     * 批量删除时间账本
     *
     * @param ids 需要删除的时间账本主键
     * @return 结果
     */
    @Override
    public int deleteTimeRecordByIds(Long[] ids)
    {
                return removeByIds(Arrays.asList(ids)) == true ? 1 : 0;
    }

    /**
     * 删除时间账本信息
     *
     * @param id 时间账本主键
     * @return 结果
     */
    @Override
    public int deleteTimeRecordById(Long id)
    {
                return removeById(id) == true ? 1 : 0;
    }

    @Override
    public List<TimeRecordDailyStatisticsVo> getMonthlyTimeStatistics(Long userId, Integer year, Integer month) {
        // 获取指定年月的所有日期
        List<LocalDate> datesInMonth = getDatesInMonth(year, month);

        // 查询该月的所有时间记录
        List<TimeRecord> timeRecords = timeRecordMapper.selectMonthlyRecords(userId, year, month);
        // 按日期分组时间记录
        Map<LocalDate, List<TimeRecord>> recordsByDate = timeRecords.stream()
                .collect(Collectors.groupingBy(TimeRecord::getRecordDate));

        List<TimeRecordDailyStatisticsVo> result = new ArrayList<>();

        for (LocalDate date : datesInMonth) {
            TimeRecordDailyStatisticsVo dailyStat = new TimeRecordDailyStatisticsVo();
            dailyStat.setDate(date);

            List<TimeRecord> dailyRecords = recordsByDate.getOrDefault(date, new ArrayList<>());

            if (!dailyRecords.isEmpty()) {
                // 计算当天总时间
                BigDecimal totalHours = dailyRecords.stream()
                        .map(TimeRecord::getDurationHours)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                dailyStat.setTotalHours(totalHours);

                // 按分类分组并计算统计信息
                List<TimeRecordCategoryDetailVo> categoryDetails = groupActivitiesByCategory(dailyRecords, totalHours);
                dailyStat.setCategoryActivities(categoryDetails);
            } else {
                // 当天没有记录，传空列表
                dailyStat.setTotalHours(BigDecimal.ZERO);
                dailyStat.setCategoryActivities(new ArrayList<>());
            }

            result.add(dailyStat);
        }

        return result;
    }

    /**
     * 将活动列表按分类分组并计算统计信息
     */
    private List<TimeRecordCategoryDetailVo> groupActivitiesByCategory(List<TimeRecord> activities, BigDecimal dailyTotalHours) {
        if (activities.isEmpty()) {
            return new ArrayList<>();
        }

        // 按分类(activityName)分组
        Map<String, List<TimeRecord>> groupedByCategory = activities.stream()
                .collect(Collectors.groupingBy(TimeRecord::getActivityName));

        List<TimeRecordCategoryDetailVo> result = new ArrayList<>();

        for (Map.Entry<String, List<TimeRecord>> entry : groupedByCategory.entrySet()) {
            TimeRecordCategoryDetailVo categoryDetail = new TimeRecordCategoryDetailVo();
            categoryDetail.setCategoryName(entry.getKey());

            List<TimeRecord> categoryActivities = entry.getValue();
            ArrayList<TimeRecordVo> timeRecordVos = new ArrayList<>();
            categoryActivities.forEach(activity -> {
                TimeRecordVo timeRecordVo = new TimeRecordVo();
                BeanUtils.copyProperties(activity, timeRecordVo);
                timeRecordVos.add(timeRecordVo);
            });

            categoryDetail.setActivities(timeRecordVos);

            // 计算该分类总时间
            BigDecimal categoryTotalHours = categoryActivities.stream()
                    .map(TimeRecord::getDurationHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            categoryDetail.setTotalHours(categoryTotalHours);

            // 计算百分比
            double percentage = dailyTotalHours.compareTo(BigDecimal.ZERO) > 0 ?
                    categoryTotalHours.multiply(BigDecimal.valueOf(100))
                            .divide(dailyTotalHours, 2, RoundingMode.HALF_UP)
                            .doubleValue() : 0.0;
            categoryDetail.setPercentage(percentage);

            result.add(categoryDetail);
        }

        // 按时间从大到小排序
        result.sort((a, b) -> b.getTotalHours().compareTo(a.getTotalHours()));

        return result;
    }

    @Override
    public TimeRecordWeeklyStatisticsVo getWeeklyTimeStatisticsByCategory(Long userId) {
        // 获取本周的开始和结束日期
        LocalDate today = LocalDate.now();
        LocalDate weekStart = today.with(DayOfWeek.MONDAY);
        LocalDate weekEnd = today.with(DayOfWeek.SUNDAY);

        // 查询本周的所有时间记录
        List<TimeRecord> timeRecords = timeRecordMapper.selectWeeklyRecordsByCategory(userId, weekStart, weekEnd);

        if (timeRecords.isEmpty()) {
            return new TimeRecordWeeklyStatisticsVo();
        }

        // 按活动类型分组并计算总时间
        Map<String, List<TimeRecord>> recordsByCategory = timeRecords.stream()
                .collect(Collectors.groupingBy(TimeRecord::getActivityName));

        // 计算本周总时间
        BigDecimal totalWeekHours = timeRecords.stream()
                .map(TimeRecord::getDurationHours)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 构建统计结果
        List<TimeRecordCategoryStatisticsVo> result = new ArrayList<>();

        for (Map.Entry<String, List<TimeRecord>> entry : recordsByCategory.entrySet()) {
            String categoryName = entry.getKey();
            List<TimeRecord> categoryRecords = entry.getValue();

            // 计算该类型总时间
            BigDecimal categoryTotalHours = categoryRecords.stream()
                    .map(TimeRecord::getDurationHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 计算百分比
            double percentage = totalWeekHours.compareTo(BigDecimal.ZERO) > 0 ?
                    categoryTotalHours.multiply(BigDecimal.valueOf(100))
                            .divide(totalWeekHours, 2, RoundingMode.HALF_UP)
                            .doubleValue() : 0.0;

            TimeRecordCategoryStatisticsVo statisticsVo = new TimeRecordCategoryStatisticsVo();
            statisticsVo.setCategoryName(categoryName);
            statisticsVo.setTotalHours(categoryTotalHours);
            statisticsVo.setPercentage(percentage);
            statisticsVo.setRecordCount(categoryRecords.size());

            result.add(statisticsVo);
        }

        // 按时间从大到小排序
        result.sort((a, b) -> b.getTotalHours().compareTo(a.getTotalHours()));

        // 计算总花费时间之和
        BigDecimal totalCostTimeSum = result.stream()
                .map(TimeRecordCategoryStatisticsVo::getTotalHours)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        TimeRecordWeeklyStatisticsVo timeRecordWeeklyStatisticsVo = new TimeRecordWeeklyStatisticsVo();
        timeRecordWeeklyStatisticsVo.setTimeRecordCategoryStatistics( result);
        timeRecordWeeklyStatisticsVo.setTotalCostTime(totalCostTimeSum);

        return timeRecordWeeklyStatisticsVo;
    }


    /**
     * 按照月份获取时间账本的分类统计信息
     * @param userId
     * @param year
     * @return
     */
    @Override
    public TimeRecordMonthlyCategoryStatisticsVo getMonthlyCategoryStatistics(Long userId, Integer year, Integer month) {
            // 查询指定年月的所有时间记录
            List<TimeRecord> timeRecords = timeRecordMapper.selectMonthlyRecords(userId, year, month);

            TimeRecordMonthlyCategoryStatisticsVo monthlyStat = new TimeRecordMonthlyCategoryStatisticsVo();
            monthlyStat.setYear(year);
            monthlyStat.setMonth(month);
        // 计算总花费时间之和
        BigDecimal totalCostTimeSum = timeRecords.stream()
                .map(TimeRecord::getDurationHours)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            monthlyStat.setTotalCostTime(totalCostTimeSum);
            if (!timeRecords.isEmpty()) {
                // 按分类分组并计算统计信息
                List<TimeRecordCategoryStatisticsVo> categoryStats = buildCategoryStatistics(timeRecords);
                monthlyStat.setCategoryStatistics(categoryStats);
            } else {
                // 这个月没有记录，返回空列表
                monthlyStat.setCategoryStatistics(new ArrayList<>());
            }


        return monthlyStat;
    }

    @Override
    public TimeRecordDailyStatisticsVo getDailyTimeStatisticsByDate(Long userId, LocalDate date) {
        // 查询指定日期的时间记录
        List<TimeRecord> timeRecords = timeRecordMapper.selectByDateAndUser(userId, date);
        // 构建统计信息
        return buildDailyStatistics(date, timeRecords);
    }

    @Override
    public List<TimeRecord> getTimeRecordsByDate(Long userId, LocalDate date) {
        List<TimeRecord> timeRecords = timeRecordMapper.selectTimeRecordsByDate(userId, date);
        return timeRecords;
    }

    private TimeRecordDailyStatisticsVo buildDailyStatistics(LocalDate date, List<TimeRecord> dailyRecords) {
        TimeRecordDailyStatisticsVo vo = new TimeRecordDailyStatisticsVo();
        vo.setDate(date);

        if (!dailyRecords.isEmpty()) {
            // 计算当天总时间
            BigDecimal totalHours = dailyRecords.stream()
                    .map(TimeRecord::getDurationHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setTotalHours(totalHours);

            // 按分类统计时间
            List<TimeRecordCategoryDetailVo> categoryDetails = groupActivitiesByCategory(dailyRecords, totalHours);
            vo.setCategoryActivities(categoryDetails);
        } else {
            vo.setTotalHours(BigDecimal.ZERO);
            vo.setCategoryActivities(new ArrayList<>());
        }

        return vo;
    }


    /**
     * 构建分类统计信息
     */
    private List<TimeRecordCategoryStatisticsVo> buildCategoryStatistics(List<TimeRecord> timeRecords) {
        if (timeRecords.isEmpty()) {
            return new ArrayList<>();
        }

        // 按活动类型分组
        Map<String, List<TimeRecord>> recordsByCategory = timeRecords.stream()
                .collect(Collectors.groupingBy(TimeRecord::getActivityName));

        // 计算总时间
        BigDecimal totalHours = timeRecords.stream()
                .map(TimeRecord::getDurationHours)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 构建统计结果
        List<TimeRecordCategoryStatisticsVo> result = new ArrayList<>();

        for (Map.Entry<String, List<TimeRecord>> entry : recordsByCategory.entrySet()) {
            String categoryName = entry.getKey();
            List<TimeRecord> categoryRecords = entry.getValue();

            // 计算该分类总时间
            BigDecimal categoryTotalHours = categoryRecords.stream()
                    .map(TimeRecord::getDurationHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 计算百分比
            double percentage = totalHours.compareTo(BigDecimal.ZERO) > 0 ?
                    categoryTotalHours.multiply(BigDecimal.valueOf(100))
                            .divide(totalHours, 2, RoundingMode.HALF_UP)
                            .doubleValue() : 0.0;

            TimeRecordCategoryStatisticsVo statisticsVo = new TimeRecordCategoryStatisticsVo();
            statisticsVo.setCategoryName(categoryName);
            statisticsVo.setTotalHours(categoryTotalHours);
            statisticsVo.setPercentage(percentage);
            statisticsVo.setRecordCount(categoryRecords.size());

            result.add(statisticsVo);
        }

        // 按时间从大到小排序
        result.sort((a, b) -> b.getTotalHours().compareTo(a.getTotalHours()));

        return result;
    }

    /**
     * 获取指定年月的所有日期
     */
    private List<LocalDate> getDatesInMonth(int year, int month) {
        List<LocalDate> dates = new ArrayList<>();
        YearMonth yearMonth = YearMonth.of(year, month);
        int daysInMonth = yearMonth.lengthOfMonth();

        for (int day = 1; day <= daysInMonth; day++) {
            dates.add(LocalDate.of(year, month, day));
        }

        return dates;
    }

}